package com.angel.bo.business.config.aspect;


import com.angel.bo.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 日志记录AOP工具类，环绕通知
 *
 * @Author: Haibo.Mei [Haibo.Mei@ge.com]
 * @Description:
 * @Date: 16:39 2017/12/6
 */
@Slf4j
@Aspect
@Order(5)
@Component
public class LogAspectService {

    /**
     * 定义切面，此方法不能有返回值，该方法只是一个标示，方法体不会被执行
     */
    @Pointcut("execution( * com.angel.bo.*.service..*(..))")
    private void recordLog() {
    }

    /**
     * 环绕通知，决定真实的方法是否执行，而且必须有返回值。 同时在所拦截方法的前后执行一段逻辑。
     *
     * @param pjp 连接点
     * @return 执行方法的返回值
     * @throws Throwable 抛出异常
     */
    @Around("recordLog()")
    @SuppressWarnings("ALL")
    public Object aroundLogCalls(ProceedingJoinPoint pjp) throws Throwable {
        String className = pjp.getTarget().getClass().getName();
        // 获得方法名
        String methodName = pjp.getSignature().getName();
        // 获得参数列表
        Object[] args = pjp.getArgs();
        long threadId = Thread.currentThread().getId();
        if (log.isDebugEnabled()) {
            log.info("[LogAspectService]--Start-[CLASSNAME:{}],[METHODNAME:{}],[THREADID：{}]，[ARGS：{}]",
                    className,
                    methodName,
                    threadId,
                    JsonUtil.toJson(args));
        }
        // 执行完方法的返回值：调用proceed()方法，就会触发切入点方法执行
        // procObject的值就是被拦截方法的返回值
        Object result = pjp.proceed();
        if (log.isDebugEnabled()) {
            log.info("[LogAspectService]--End-[CLASSNAME:{}],[METHODNAME:{}],[THREADID：{}]，[RESULT：{}]",
                    className,
                    methodName,
                    threadId,
                    JsonUtil.toJson(result));
        }
        return result;
    }
}
